iT邦幫忙

2023 iThome 鐵人賽

DAY 3
1
Modern Web

就是個Go,我也可以啦!GOGO系列 第 3

2023鐵人賽Day 3 Go怎麼傳值,先讀懂指標-2

  • 分享至 

  • xImage
  •  

理解記憶體管理:stack(堆疊) & heap(堆積)

stack(堆疊)

  • 假設把程式的變數想成很多盒子要準備整理,堆疊就是把這些盒子整齊堆放,先進來的就先堆起來,堆滿了就從最上面的盒子一個個拿走,這就是後進先出的蓋念
  • 堆疊記憶體空間是一個暫時性的記憶體空間,用來保存暫時性變數(區域變數)
  • 生命週期短:存放在堆疊的變數的生命週期與所在的函數或區塊相同
  • 空間有限:堆疊的大小有限制,使用過多就會導致堆疊溢出

heap(堆積)

  • 堆積就是胡亂堆積盒子,有地放就擺,沒有順序性
  • 堆積的大小通常比堆疊更大,所以更適合大型物件或陣列
  • 生命週期長,存放在堆積中的物件生命週期不受函數調用的限制
  • 分配速度慢:與堆疊相比,堆積的記憶體分配較慢,因為它涉及到更複雜的記憶體管理。

Go指標與堆積

  • go的指標是儲存變數記憶體地址的變數,可以透過new()就會於堆積內分配一個記憶體空間並賦予零值
  • 一旦值設置了指標,就等於把值放盡了堆積
  • Go語言會使用逃逸分析的程序去判斷是否要放在堆積上,所以有可能值沒有設置指標,但卻被放在堆積上

Pass by Value & Pass by ref

Go 語言中的函數調用是按值傳遞的,也就是在函式內是複製一份,而不是使用原本的變數

pakage main

import (
  "fmt"
)

func modifyValue(x int) {
	x = x + 1
}

func main() {
  original := 1
  modifyValue(original)
  fmt.Println(original) // 輸出 1,value 的值沒有改變
}

簡單的原理就是,他會在stack堆疊內複製一份,並使用那一份進行運算

pass by value好處

  • 不會有副作用的影響: 任何在函數內部對變數的修改都不會影響到原始變數
  • 可讀性跟維護性高:沒有副作用也就能防止很多潛在的錯誤,按值傳遞有助於保護數據的完整性
  • 並發安全:在 Go 的並發環境中,按值傳遞有助於減少競爭條件

pass by value 壞處

  • 當複製資料時,依據資料大小及資料複雜度,會消耗比傳指標位置還多的cpu資源
  • 如果沒有控制好會造成stack overflow

pass by ref (用指標進行傳遞)

與按值傳遞不同,按引用傳遞不會複製傳遞的值。然而,這代表你必須更小心處理可能的副作用,因為函數內部的更改可能會影響呼叫函數的其他部分

package main

import "fmt"

func modifyValue(ptr *int) {
	*ptr = 10
}

func main() {
	value := 5
	fmt.Println("Before:", value) // 輸出 "Before: 5"
	modifyValue(&value)
	fmt.Println("After:", value)  // 輸出 "After: 10"
}

pass by ref 好處

  • 可以減少cpu用量
  • 能夠修改原始數據
  • 減少記憶體使用

pass by ref 壞處

  • 只要是放在堆疊,就代表他需要仰賴繁瑣的垃圾回收機制,這機制可能會是造成CPU瓶頸的原因,若堆積有大量資料,那垃圾回收機制就必須做大量的檢查

我該用哪個

列幾個因素歸納整理,可以依據下面因素去決定自己該用哪一個

  • 併發安全性:在併發環境中,pass by value 可以減少競爭條件及副作用的風險
  • 可讀性和維護性:按值傳遞更容易理解和維護,因為他不影響原始數據
  • 數據大小和複雜度:數據弱很大很複雜,複製值會消耗很多資源,此時用傳遞指標反而更高效
  • 函數的角色和責任:如果函數本身就是用來操作及變更某種數據結構,那傳遞指標更合適
  • 性能及消耗:複製值是一種cpu的消耗,但垃圾回收機制也是一種負擔,故要衡量
  • 是否需要修改原始數據

上一篇
2023鐵人賽Day 2 Go怎麼傳值,先讀懂指標-1
下一篇
2023鐵人賽Day 4 Go的DRY藝術 - 使用套件
系列文
就是個Go,我也可以啦!GOGO30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言